package com.iotechn.unimall.app.quartz;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.iotechn.unimall.biz.service.distribution.DistributionBizService;
import com.iotechn.unimall.biz.service.tree.TreeBizService;
import com.iotechn.unimall.biz.service.order.OrderBizService;
import com.iotechn.unimall.data.component.LockComponent;
import com.iotechn.unimall.data.domain.*;
import com.iotechn.unimall.data.enums.OrderStatusType;
import com.iotechn.unimall.data.mapper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by rize on 2019/7/21.
 */
@Component
@EnableScheduling
public class CheckQuartz {

    private static final Logger logger = LoggerFactory.getLogger(CheckQuartz.class);
    private static final String ORDER_STATUS_LOCK = "ORDER_STATUS_QUARTZ_LOCK";
    private static final String TREE_ORDER_STATUS_LOCK = "TREE_ORDER_STATUS_QUARTZ_LOCK";
    private static final String GROUP_SHOP_START_LOCK = "GROUP_SHOP_START_LOCK";
    private static final String GROUP_SHOP_END_LOCK = "GROUP_SHOP_END_LOCK";
    private static final String GROUP_SHOP_LOCK_LOCK = "GROUP_SHOP_LOCK_LOCK";
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderBizService orderBizService;
    @Autowired
    private DistributionBizService distributionBizService;
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private OrderSkuMapper orderSkuMapper;
    @Autowired
    private LockComponent lockComponent;
    @Autowired
    private TreeOrderMapper treeOrderMapper;
    @Autowired
    private TreeDetailsOrderMapper treeOrderDetailsMapper;
    @Autowired
    private TreeDetailsMapper treeDetailsMapper;
    @Autowired
    private TreeBizService treeBizService;
    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 订单状态定时轮训
     */
    @Scheduled(cron = "0 * * * * ?")
    public void checkOrderStatus() {
        if (lockComponent.tryLock(ORDER_STATUS_LOCK, 15)) {
            try {
                Date now = new Date();
                // 请注意，此处并非查出订单的所有信息，若需要其他字段，请自行添加
                List<OrderDO> nos = orderMapper.selectExpireOrderNos(OrderStatusType.UNPAY.getCode(), new Date(now.getTime() - 1000l * 60 * 15));
                if (!CollectionUtils.isEmpty(nos)) {
                    nos.forEach(no -> {
                        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                            @Override
                            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                                try {
                                    OrderDO updateOrderDO = new OrderDO();
                                    updateOrderDO.setStatus(OrderStatusType.CANCELED_SYS.getCode());
                                    updateOrderDO.setGmtUpdate(now);
                                    List<OrderSkuDO> orderSkuList = orderSkuMapper.selectList(new EntityWrapper<OrderSkuDO>().eq("order_id", no.getId()));
                                    orderSkuList.forEach(item -> {
                                        spuMapper.returnSkuStock(item.getSkuId(), item.getNum());
                                    });
                                    Long distributionDeductionId = no.getDistributionDeductionId();
                                    if (distributionDeductionId != null) {
                                        // 退还分销用户佣金
                                        distributionBizService.returnDeduction(updateOrderDO,distributionDeductionId, null, no.getUserId());
                                    }
                                    orderBizService.changeOrderStatus(no.getOrderNo(), OrderStatusType.UNPAY.getCode(), updateOrderDO);
                                } catch (Exception e) {
                                    logger.error("[未付款检测] 异常", e);
                                    transactionStatus.setRollbackOnly();
                                }
                            }
                        });
                    });
                }
                //15分钟执行一次
                long minutes = (now.getTime() / (1000 * 60));
                if (minutes % 15 == 0) {
                    List<OrderDO> waitConfirmNos = orderMapper.selectExpireOrderNos(OrderStatusType.WAIT_CONFIRM.getCode(), new Date(now.getTime() - 1000l * 60 * 60 * 24 * 7));
                    waitConfirmNos.forEach(item -> {
                        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                            @Override
                            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                                try {
                                    OrderDO updateOrderDO = new OrderDO();
                                    updateOrderDO.setStatus(OrderStatusType.WAIT_APPRAISE.getCode());
                                    updateOrderDO.setGmtUpdate(now);
                                    List<OrderSkuDO> orderSkuList = orderSkuMapper.selectList(new EntityWrapper<OrderSkuDO>().eq("order_id", item.getId()));
                                    orderSkuList.forEach(skuItem -> {
                                        spuMapper.decSkuFreezeStock(skuItem.getSkuId(), skuItem.getNum());
                                    });
                                    if (item.getDistributionId() != null) {
                                        distributionBizService.unfreezeOrder(item.getOrderNo());
                                    }
                                    Long distributionDeductionId = item.getDistributionDeductionId();
                                    if (distributionDeductionId != null) {
                                        // 退还分销用户佣金
                                        distributionBizService.confirmDeduction(distributionDeductionId, item.getUserId());
                                    }
                                    orderBizService.changeOrderStatus(item.getOrderNo(), OrderStatusType.WAIT_CONFIRM.getCode(), updateOrderDO);
                                } catch (Exception e) {
                                    logger.error("[未确认检测] 异常", e);
                                    transactionStatus.setRollbackOnly();
                                }
                            }
                        });

                    });
                }
            } catch (Exception e) {
                logger.error("[订单状态检测定时任务] 异常", e);
            } finally {
                lockComponent.retree(ORDER_STATUS_LOCK);
            }
        }
    }




    @Scheduled(cron = "0 * * * * ?")
    public void checkTreeOrderStatus() {
        if (lockComponent.tryLock(TREE_ORDER_STATUS_LOCK, 15)) {
            try {
                Date now = new Date();
                // 请注意，此处并非查出订单的所有信息，若需要其他字段，请自行添加
                List<TreeOrderDO> nos = treeOrderMapper.selectExpireOrderNos(OrderStatusType.UNPAY.getCode(), new Date(now.getTime() - 1000l * 60 * 15));
                if (!CollectionUtils.isEmpty(nos)) {
                    nos.forEach(no -> {
                        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                            @Override
                            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                                try {
                                    TreeOrderDO updateOrderDO = new TreeOrderDO();
                                    updateOrderDO.setStatus(OrderStatusType.CANCELED_SYS.getCode());
                                    updateOrderDO.setGmtUpdate(now);
                                    List<TreeDetailOrderDO> orderList = treeOrderDetailsMapper.selectList(new EntityWrapper<TreeDetailOrderDO>().eq("order_id", no.getId()));
                                    orderList.forEach(item -> {
                                        treeDetailsMapper.updateStatus(item.getTreeDetailId(),0,1);
                                    });
                                    treeBizService.changeOrderStatus(no.getOrderNo(), OrderStatusType.UNPAY.getCode(), updateOrderDO);
                                } catch (Exception e) {
                                    logger.error("[未付款检测] 异常", e);
                                    transactionStatus.setRollbackOnly();
                                }
                            }
                        });
                    });
                }
            } catch (Exception e) {
                logger.error("[订单状态检测定时任务] 异常", e);
            } finally {
                lockComponent.retree(ORDER_STATUS_LOCK);
            }
        }
    }

}
